﻿var PMChat = jQuery.extend(PMChat,
{
    UI: {
        Config: {
            Container: document.body,
            UseEmoticons: true,
            SiteHostName: "unknown",
            SiteImagePath: "unknown",
            Audio: {
                NewMessage: ["~/content/audio/newmsg1.mp3", "~/content/audio/newmsg1.wav"]
            }
        },

        On: function (event, handler) {
            jQuery(this).on(event, handler);
            return this;
        },

        Off: function (event, handler) {
            jQuery(this).off(event, handler);
            return this;
        },

        Trigger: function (event, param) {
            jQuery(this).trigger(event, param);
            return this;
        },

        ToggleChat: function () {
            if (PMChat.Connected == true) {
                PMChat.Disconnect();
                PMChat.UI.SetToggleText();
            }
            else {
                PMChat.Connect();
                PMChat.UI.SetToggleText();
            }
        },

        Init: function (config) {
            this.Config = jQuery.extend(this.Config, config);

            this.InitAudio();

            var msgHandler = function (e, msg) {
                var from = 'recipient';
                var prepend = false;

                if (msg.Prepend && msg.Prepend == true)
                    prepend = true;

                if (msg.Sender.MemberID != e.Client.WithMember.MemberID) {
                    from = 'member';
                }

                // just in case we get the same message twice due to a delivery delay or what not...
                var existingMessage = e.Client.ChatBox.find('.chatMessage[data-messageid="' + msg.MessageID + '"]');
                if (existingMessage != null && existingMessage.length > 0)
                    return;

                var chatMsg = msg.Message;
                chatMsg = PMChat.UI.Emotificate(chatMsg);
                chatMsg = PMChat.UI.ProcessUrls(chatMsg)
                msg.Message = chatMsg;

                if (e.Client.ChatBox.children('.chatTabContent').children('div.chatMessageGroup:' + (prepend ? 'first' : 'last')).hasClass(from)) {
                    var existGroup = e.Client.ChatBox.children('.chatTabContent').children('div:' + (prepend ? 'first' : 'last'));
                    var newMsg = jQuery('<div class="chatMessage" />').attr('data-messageid', msg.MessageID).html(msg.Message);
                    if (prepend) {
                        existGroup.find('.chatMessages').prepend(newMsg);
                    }
                    else {
                        existGroup.find('.chatMessages').append(newMsg);
                        newMsg.parent().parent().find('div > span:nth-child(2)').html(PMChat.UI.CalculateTimeStamp(msg.TimeStamp));
                        e.Client.ChatBox.find('.chatTabContent').scrollTop(e.Client.ChatBox.find('.chatTabContent')[0].scrollHeight);
                    }
                    e.Client.ChatBox.children('.chatTabContent').parent().show();
                } else {
                    var newGroup = jQuery('<div class="chatMessageGroup"><div><span class="' + from + '">' + msg.Sender.NickName + '</span><span>' + PMChat.UI.CalculateTimeStamp(msg.TimeStamp) + '</span></div><div class="chatMessages"></div></div>');
                    newGroup.addClass(from);
                    var mhtml = jQuery('<div class="chatMessage"/>').attr('data-messageid', msg.MessageID).html(msg.Message);
                    newGroup.find('.chatMessages').append(mhtml);
                    if (prepend) {
                        e.Client.ChatBox.children('.chatTabContent').prepend(newGroup);
                    } else {
                        e.Client.ChatBox.children('.chatTabContent').append(newGroup);
                        e.Client.ChatBox.find('.chatTabContent').scrollTop(e.Client.ChatBox.find('.chatTabContent')[0].scrollHeight);
                    }
                }

                if ((msg.Acknowledged == false && msg.Sender.MemberID == e.Client.WithMember.MemberID) || e.Client.WithMember.NewMessage == true)
                    PMChat.UI.NewMessage(e.Client);

                if (jQuery('.lt-ie9').length > 0) {
                    //style fixes for ie8 and below
                    e.Client.ChatBox.find('.chatTabContent > div:last-child').addClass('lastTransmission');
                }

                e.Client.ChatBox.find('.chatMessage > a').click(function () {
                    var a = jQuery(this);
                    var memberId = e.Client.WithMember.MemberID;
                    var nickname = e.Client.WithMember.NickName;
                    var msgId = a.parent().attr('data-messageid');
                    var url = a.attr('data-href');

                    linkEvt = new jQuery.Event("showexternallink");
                    PMChat.UI.Trigger(linkEvt, { MemberId: memberId, NickName: nickname, MessageId: msgId, URL: url });
                });
                

            };

            PMChat.On('open', function (e) {
                var client = e.Client;
                if (!client.ChatBox) {
                    client.ChatBox = PMChat.UI.CreateChatBox(client);
                }
                client.On('message', msgHandler);

                client.On("composing", function(e, result) {
                    var isComposing = result.IsComposing;
                    if (isComposing == true) {
                        var chatStatus = client.ChatBox.find('.chatTabStatus');
                        
                        chatStatus.html(client.WithMember.NickName + ' is typing a message ...');
                        chatStatus.show();
                    } else {
                        client.ChatBox.find('.chatTabStatus').hide();
                    }
                });

                client.On('getchat', function (e, result) {
                    var firstGroup = null;
                    if (e.Client.ChatBox.children('.chatTabContent:first').children('.chatMessageGroup').length > 1) {
                        firstGroup = e.Client.ChatBox.children('.chatTabContent:first').children('.chatMessageGroup:first');
                    }
                    if (firstGroup != null && firstGroup.length > 0) {
                        firstGroup = jQuery(firstGroup[0]);
                    } else {
                        firstGroup = null;
                    }

                    var chat = result.Chat;

                    if (chat && chat != null) {
                        var updatedWithMember = chat.WithMember;
                        var ageLocation = e.Client.ChatBox.find('.chatTabUser > span');
                        ageLocation.html(updatedWithMember.Age + ' | ' + updatedWithMember.Location.City + ', ' + updatedWithMember.Location.StateCode);
                    }

                    if (chat == null || chat.Messages == null) return;

                    for (var m in chat.Messages) {
                        var chatMsg = chat.Messages[m];

                        if (Object.prototype.toString.call(chatMsg) == "[object Function]") continue;

                        chatMsg.Prepend = true;
                        msgHandler(e, chatMsg);
                    }

                    if (result.Chat.Messages.length >= 20) {
                        var historyLink = e.Client.ChatBox.find('.chatTabContentHistoryLink:first');
                        historyLink.remove();
                        historyLink = jQuery('<a class="chatTabContentHistoryLink" href="#">Load earlier messages</a>').click(function (e) {
                            PMChat.UI.GetChatHistory(client);
                            return false;
                        });
                        e.Client.ChatBox.find('.chatTabContent').prepend(historyLink);
                    }

                    if (result.Chat.Messages.length < 20) {
                        e.Client.ChatBox.find('.chatTabContentHistoryLink').remove();
                    }

                    var favoriteText = 'Save as Favorite';
                    if (e.Client.WithMember.IsFavorite)
                        favoriteText = 'Remove from Favorites';

                    var favoriteLocation = e.Client.ChatBox.find('.chatTabSettingsMenu > div > div:first-child');
                    favoriteLocation.html(favoriteText);

                    // so if we already have chat messages, try to remember which one used to be first and scroll back there, otherwise scroll all the way to bottom...
                    if (firstGroup != null) {
                        var haveHistoryLink = e.Client.ChatBox.children('.chatTabContent:first').children('.chatTabContentHistoryLink:first');
                        e.Client.ChatBox.find('.chatTabContent').scrollTop(firstGroup.offset().top - (firstGroup.outerHeight() + haveHistoryLink.outerHeight()));
                        firstGroup.scrollTop(haveHistoryLink.height());
                    } else {
                        e.Client.ChatBox.find('.chatTabContent').scrollTop(e.Client.ChatBox.find('.chatTabContent')[0].scrollHeight);
                    }
                });

                client.On("presence", function (e, data) {
                    if (e.Client && e.Client != null) {
                        e.Client.ChatBox.find('.chatTabUser > img:nth-child(2)').attr("src", PMChat.Config.BaseUrl + "/presence/icon/" + e.Client.WithMember.SiteID + "/" + e.Client.WithMember.MemberID);
                    }
                });

                client.On("hasnewmessage", function (e) {
                    if (PMChat.UI.Config.Audio && PMChat.UI.Config.Audio.NewMessage) {
                        try {
                            PMChat.UI.Config.Audio.NewMessage.play();
                        } catch (ex) { }
                    }
                });
                
                client.On("sent", function (e) {
                    var chatStatus = e.Client.ChatBox.find('.chatTabStatus');
                    if (e.Client.WithMember.Status.Presence == 0) {
                        chatStatus.html(e.Client.WithMember.NickName + ' is offline ...');
                        chatStatus.show();
                    }
                    if (e.Client.WithMember.Status.Presence == 1) {
                        chatStatus.hide();
                    }
                });
                
                client.On('senderror', function (err) {
                    if (err.Error.getCode() == 4401) {
                        PMChat.UI.SessionExpired(err, true);
                    } else {
                        if (err.Error.getCode() > 0 && err.Error.getCode() < 4000) {
                            err.Error.Handled = true;
                        }

                        PMChat.UI.DisplayClientError(err.Client.WithMember.MemberID, PMChat.ErrorManager.GetErrorMessage(err.Error));
                    }
                });

                client.On('ackerror', function (err) {
                    if (err.Error.getCode() == 4401) {
                        PMChat.UI.SessionExpired(err, false);
                    } else {
                        PMChat.UI.DisplayClientError(err.Client.WithMember.MemberID, PMChat.ErrorManager.GetErrorMessage(err.Error));
                    }
                });

                client.Get({ MessageCount: 20 });
                
            });

            PMChat.On('close', function (e) {
                var client = e.Client;
                client.Off('message', msgHandler);
                PMChat.UI.CloseTab(client);
            });

            PMChat.On('getchatserror', function (error) {
                // There is no specific chat client for this one...
                PMChat.UI.DisplayError(PMChat.ErrorManager.GetErrorMessage(error.Error));
            });

            this.Build();

            e = new jQuery.Event("ready");
            this.Trigger(e);

            return this;
        },

        SetToggleText: function () {
            if (PMChat.Connected == true) {
                jQuery("#usernameMenuChatStatusText").text("Turn Chat Off");
                jQuery("#usernameMenuChatStatusText").parent().show();
            }
            else {
                jQuery("#usernameMenuChatStatusText").text("Turn Chat On");
                jQuery("#usernameMenuChatStatusText").parent().show();
            }
        },

        GetChatHistory: function (client) {
            var chatTab = jQuery('div.chatTab[data-with="' + client.WithMember.MemberID + '"]');
            var firstMessageID = chatTab.find('.chatMessage:first').attr('data-messageid');
            client.Get({ LastMessageID: firstMessageID, MessageCount: 20 });
        },

        NewMessage: function (client) {
            var chatTab = jQuery('div.chatTab[data-with="' + client.WithMember.MemberID + '"]');
            if (chatTab.hasClass('unAck') || chatTab.hasClass('focusTab'))
                return;
            chatTab.addClass('unAck');

            client.WithMember.NewMessage = true;
            PMChat.SaveState();

            var flash = window.setInterval(function () {
                if (chatTab.hasClass('unAck'))
                    chatTab.toggleClass('newMessage');
                else {
                    chatTab.removeClass('newMessage');
                    window.clearInterval(flash);
                }
            }, 1000);
        },

        ToggleMinMax: function (e) {
            var client = e.data;
            var minimized = (client.WithMember.ChatMinimized || false);
            PMChat.UI.SetMinMax(client, minimized ? false : true);
        },

        GoToProfile: function (e) {
            var client = e.data;
            location.href = 'http://' + PMChat.UI.Config.SiteHostName + '/v3/profile?profile=' + client.WithMember.MemberID;
        },

        SetMinMax: function (client, minimized) {
            var animate = true;
            var chatTab = jQuery('div.chatTab[data-with="' + client.WithMember.MemberID + '"]');
            var chatTabUser = chatTab.find('div.chatTabUser > a');
            
            if (minimized == false) {
                chatTab.removeClass('chatMinimized');
                chatTab.find('img.profile').show();
                chatTabUser.off("click", PMChat.UI.ToggleMinMax);
                chatTabUser.on("click", client, PMChat.UI.GoToProfile);
                if (animate == true) {
                    chatTab.animate({ bottom: '-4px' }, 150);
                } else {
                    chatTab.css({ bottom: '-4px' });
                }
            } else {
                var update = function () {
                    chatTab.addClass('chatMinimized');
                    chatTab.find('img.profile').hide();
                    chatTabUser.off("click", PMChat.UI.GoToProfile);
                    chatTabUser.on("click", client, PMChat.UI.ToggleMinMax);
                    chatTab.find('div.chatTabMinimize').attr('title', 'Maximize');
                    chatTab.removeClass('focusTab');
                };
                
                if (animate == true) {
                    chatTab.animate({ bottom: '-349px' }, 150, update);
                } else {
                    chatTab.css({ bottom: '-349px' });
                    update();
                }
            }

            client.WithMember.ChatMinimized = minimized;

            PMChat.SaveState();
        },

        CloseTab: function (client) {
            jQuery('div.chatTab[data-with="' + client.WithMember.MemberID + '"]').remove();
            PMChat.UI.LayoutChats();
        },

        ChatTabFocus: function (client, forceMaximize) {
            //non-standard properties for IE <9
            var x = (window.pageXOffset !== undefined) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft;
            var y = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;

            var chatTab = jQuery('div.chatTab[data-with="' + client.WithMember.MemberID + '"]');
            chatTab.addClass('focusTab').removeClass('unAck');
            chatTab.find('textarea').focus();
            window.scrollTo(x, y);

            if (forceMaximize && forceMaximize == true) {
                PMChat.UI.SetMinMax(client, false);
            }

            client.WithMember.NewMessage = false;
            PMChat.SaveState();
        },

        ChatTabBlur: function (client) {
            jQuery('div.chatTab[data-with="' + client.WithMember.MemberID + '"]').removeClass('focusTab');
        },

        Build: function () {
            jQuery(document.body).append('<div id="ChatBar"><div class="chatFrame"></div></div>');
        },
        
        SetComposingStatus: function (client, isComposing) {
            client.ComposingInterval = client.ComposingInterval || null;
            if (isComposing == true) {
                if (!client.IsComposing) {
                    client.Composing(true);
                }
                client.IsComposing = true;
                window.clearInterval(client.ComposingInterval);
                client.ComposingInterval = window.setInterval(function () {
                    PMChat.UI.SetComposingStatus(client, false);
                }, 10000);
            } else {
                if (client.IsComposing == true) {
                    client.Composing(false);
                }
                client.IsComposing = false;
                window.clearInterval(client.ComposingInterval);
            }
        },

        CreateChatBox: function (client) {
            var profilePhoto = client.WithMember.PhotoUrl;
            if (profilePhoto == null)
                profilePhoto = PMChat.UI.Config.SiteImagePath + '/contentimages/stock/nophoto-' + client.WithMember.Gender + '.gif';

            var presence = "Offline";

            if (client.WithMember != null && (!client.WithMember.Status || client.WithMember.Status == null)) {
                presence = "Online";
            } else if (client.WithMember != null && client.WithMember.Status.Presence == 1) {
                presence = "Online";
            }

            var age = '';
            var city = '';
            var state = '';

            if (client.WithMember.Age) {
                age = client.WithMember.Age;
            }

            if (client.WithMember.Location) {
                city = client.WithMember.Location.City;
                state = client.WithMember.Location.StateCode;
            }

            if (age == null)
                age = '';
            if (city == null)
                city = '';
            if (state == null)
                state = '';

            var favoriteText = 'Save as Favorite';
            if (client.WithMember.IsFavorite == true)
                favoriteText = 'Remove from Favorites';

            var cWin = jQuery('<div class="chatTab" data-type="chat"></div>').attr('data-with', client.WithMember.MemberID);
            cWin.Client = client;
            cWin.append(jQuery('<div class="chatTabSettingsMenu" style="display:none;"><div><div>' + favoriteText + '</div><div>Block Member</div><div>Report a Concern</div></div>'));
            cWin.append(jQuery('<div class="chatTabUser"></div>').html('<img src="' + profilePhoto + '" class="profile" alt="" /><img src="' + PMChat.Config.BaseUrl + '/presence/icon/' + client.WithMember.SiteID + '/' + client.WithMember.MemberID + '" title="' + presence + '" alt="" /><a href="javascript:;">' + client.WithMember.NickName + '</a><span>' + age + ' | ' + city + ', ' + state + '</span><div class="chatTabClose" title="Close"></div><div class="chatTabSettings" title="Settings"></div><div class="chatTabMinimize" title="Minimize"></div>'));
            cWin.append(jQuery('<div class="chatTabContent"></div>'));
            cWin.append(jQuery('<div class="chatTabStatus">sup</div>'));
            cWin.append(jQuery('<div class="chatTabEntry">').append(jQuery('<textarea class="chatTabEntryText" maxlength="300" placeholder="Write message..."></textarea><div>Send</div>')
                .keypress(function (e) {
                    cWin.find('div.chatTabEntry > div').addClass('btnActive');
                    if (e.which == 13) {
                        cWin.find('div.chatTabEntry > div').removeClass('btnActive');
                        e.preventDefault();
                        var msg = jQuery(e.target).val();
                        jQuery(e.target).val('');
                        if (msg != null && msg != '') {
                            client.Send(msg);
                        }
                        PMChat.UI.SetComposingStatus(client, false);
                    } else {
                        PMChat.UI.SetComposingStatus(client, true);
                    }
            })));

            jQuery('#ChatBar > .chatFrame').append(cWin);

            this.LayoutChats();

            var minimized = client.WithMember.ChatMinimized || false;
            PMChat.UI.SetMinMax(client, minimized);

            //send button
            cWin.find('div.chatTabEntry > div').click(function () {
                var msg = jQuery(this).parent().find('textarea').val();
                jQuery(this).parent().find('textarea').val('');
                if (msg != null && msg != '' && msg != 'Write message...') {
                    client.Send(msg);
                    PMChat.UI.SetComposingStatus(client, false);
                    cWin.find('div.chatTabEntry > div').removeClass('btnActive');
                }
            });

            //focus event
            cWin.click(function () {
                PMChat.UI.ChatTabFocus(client);
            });

            //lose focus event
            jQuery('body').click(function (e) {
                if (jQuery(e.target).is('div.chatTab[data-with="' + client.WithMember.MemberID + '"] *') || jQuery(e.target).is('[src*=onlinechatbutton]'))
                    return;
                PMChat.UI.ChatTabBlur(client);
            });

            //close chat
            cWin.find('div.chatTabClose').click(function () {
                client.Close();
            });

            cWin.find('div.chatTabUser > img:first-child').on("click", client, PMChat.UI.GoToProfile);

            //bind favorite
            cWin.find('div.chatTabSettingsMenu > div > div:first-child').click(function () {
                favoriteEvt = new jQuery.Event("togglefavorite");
                PMChat.UI.Trigger(favoriteEvt, { MemberId: client.WithMember.MemberID, IsFavorite: client.WithMember.IsFavorite });
            });

            //bind block user
            cWin.find('div.chatTabSettingsMenu > div > div:nth-child(2)').click(function () {
                blockEvt = new jQuery.Event("blockmember");
                PMChat.UI.Trigger(blockEvt, { MemberId: client.WithMember.MemberID, NickName: client.WithMember.NickName });
            });

            //bind report a concern
            cWin.find('div.chatTabSettingsMenu > div > div:nth-child(3)').click(function () {
                racEvt = new jQuery.Event("reportaconcern");
                PMChat.UI.Trigger(racEvt, { MemberId: client.WithMember.MemberID, NickName: client.WithMember.NickName });
            });

            //settings menu
            cWin.find('div.chatTabSettings').click(function () {
                var window = jQuery('div.chatTab[data-with="' + client.WithMember.MemberID + '"]').find('.chatTabSettingsMenu');
                if (window.css('display') == 'none') {
                    window.show();
                    jQuery(this).css('background-position', '0 16px');
                } else {
                    window.hide();
                    jQuery(this).css('background-position', '0 0');
                }

            });

            //minimize/maxamize chat
            cWin.find('div.chatTabUser').on("click", client, PMChat.UI.ToggleMinMax).children().on("click", function () {
                return false;
            });
            
            cWin.find('div.chatTabMinimize').on("click", client, PMChat.UI.ToggleMinMax);

            //autogrow chat area
            cWin.find('.chatTabEntryText').keyup(function () {
                if (jQuery('.lt-ie8').length > 0)
                    return;
                var content = jQuery(this).parent().parent().find('.chatTabContent');
                while (jQuery(this).outerHeight() < this.scrollHeight) {
                    jQuery(this).height(jQuery(this).height() + 1);
                    content.height(content.height() - 1);
                    content.scrollTop(content[0].scrollHeight);
                };
                if (jQuery(this).val() == '') {
                    jQuery(this).height(33);
                    jQuery(this).parent().parent().find('.chatTabContent').height(270);
                    cWin.find('div.chatTabEntry > div').removeClass('btnActive');
                }
            });

            if (!jQuery.support.placeholder) {
                //maxlength for textarea in IE since it's not supported
                jQuery("textarea[maxlength]").bind('input propertychange', function () {
                    var maxLength = jQuery(this).attr('maxlength');
                    if (jQuery(this).val().length > maxLength) {
                        jQuery(this).val(jQuery(this).val().substring(0, maxLength));
                    }
                });
                //placeholder for textarea in IE since it's not supported
                jQuery('[placeholder]').focus(function () {
                    var input = jQuery(this);
                    if (input.val() == input.attr('placeholder')) {
                        input.val('');
                        input.removeClass('placeholderText');
                    }
                }).blur(function () {
                    var input = jQuery(this);
                    if (input.val() == '' || input.val() == input.attr('placeholder')) {
                        input.addClass('placeholderText');
                        input.val(input.attr('placeholder'));
                    }
                }).blur();
            }

            return cWin;
        },

        SessionExpired: function (err, display) {
            if (display && display == false) return;
            PMChat.UI.DisplayClientError(err.Client.WithMember.MemberID, PMChat.ErrorManager.GetErrorMessage(err.Error));
            PMChat.Config.Channel.Close(); //The user will have to refresh page to get a new session
        },

        DisplayClientError: function (memberId, errorMsg) {
            var chatStatus = jQuery('div[data-with=' + memberId + '] > .chatTabStatus');
            chatStatus.addClass('chatError');
            chatStatus.html(errorMsg);
            chatStatus.show();
        },

        DisplayError: function (errorMsg) {
            console.error(errorMsg);
        },

        LayoutChats: function () {

            var right = 264;
            if (jQuery('.lt-ie8').length > 0) {
                right = 764;
            }
            jQuery('div[data-type="chat"]').each(function (index, el) {
                jQuery(el).css({ right: right, 'z-index': index });
                if (index < 3) {
                    right = right + (jQuery(el).width() + 16);
                }
                if (index > 3) {
                    right = 1032;
                }
            });
        },

        Emoticons: {
            Smile: {
                Matches: [":)", ":^)", ":-)", "=)", ":]"]
            },
            BigSmile: {
                Matches: [":D", ":-D", ":^D"]
            },
            Sad: {
                Matches: [":(", ":^(", ":-(", "=(", ":["]
            },
            SuperSad: {
                Matches: [":'(", ":'^(", ":'-("]
            },
            Wink: {
                Matches: [";)", ";^)", ";-)", ";]"]
            },
            Tongue: {
                Matches: [":p", ":-p", ":^p"]
            },
            Unsure: {
                Matches: [":/", ":-/", ":\\", ":-\\"]
            },
            OhFace: {
                Matches: [":o", ":-o", ":^o"]
            },
            Cool: {
                Matches: ["8)", "8-)", "8^)", "B)", "B-)", "B^)"]
            },
            Heart: {
                Matches: ["<3"]
            }
        },

        Emotificate: function (msg) {
            if (!PMChat.UI.Config.UseEmoticons) return msg;

            for (var type in PMChat.UI.Emoticons) {
                var emoti = PMChat.UI.Emoticons[type];
                var exp = "";
                for (var i = 0; i < emoti.Matches.length; i++) {
                    if (exp.length > 0) exp += "|";
                    exp += "(" + PMChat.UI._EmotiJoin(emoti.Matches[i].split('')) + ")";
                }
                msg = msg.replace(new RegExp("(http(s)?)?" + exp, 'gim'), function (m) {
                    if (m.toLowerCase().indexOf("http") === 0)
                        return m;

                    return '<span class="emoticon emoticon' + type + '"></span>';
                });
            }

            return msg;
        },

        _EmotiJoin: function (array) {
            var result = "";
            for (var i = 0; i < array.length; i++) {
                if (/\w/.test(array[i])) {
                    result += array[i];
                } else {
                    result += '\\' + array[i];
                }
            }
            return result;
        },

        ProcessUrls: function (msg) {
            var urlPattern = /(https?:\/\/)?([A-z\d\-]+\.)+((AC)|(AD)|(AE)|(AERO)|(AF)|(AG)|(AI)|(AL)|(AM)|(AN)|(AO)|(AQ)|(AR)|(ARPA)|(AS)|(ASIA)|(AT)|(AU)|(AW)|(AX)|(AZ)|(BA)|(BB)|(BD)|(BE)|(BF)|(BG)|(BH)|(BI)|(BIZ)|(BJ)|(BM)|(BN)|(BO)|(BR)|(BS)|(BT)|(BV)|(BW)|(BY)|(BZ)|(CA)|(CAT)|(CC)|(CD)|(CF)|(CG)|(CH)|(CI)|(CK)|(CL)|(CM)|(CN)|(CO)|(COM)|(COOP)|(CR)|(CU)|(CV)|(CW)|(CX)|(CY)|(CZ)|(DE)|(DJ)|(DK)|(DM)|(DO)|(DZ)|(EC)|(EDU)|(EE)|(EG)|(ER)|(ES)|(ET)|(EU)|(FI)|(FJ)|(FK)|(FM)|(FO)|(FR)|(GA)|(GB)|(GD)|(GE)|(GF)|(GG)|(GH)|(GI)|(GL)|(GM)|(GN)|(GOV)|(GP)|(GQ)|(GR)|(GS)|(GT)|(GU)|(GW)|(GY)|(HK)|(HM)|(HN)|(HR)|(HT)|(HU)|(ID)|(IE)|(IL)|(IM)|(IN)|(INFO)|(INT)|(IO)|(IQ)|(IR)|(IS)|(IT)|(JE)|(JM)|(JO)|(JOBS)|(JP)|(KE)|(KG)|(KH)|(KI)|(KM)|(KN)|(KP)|(KR)|(KW)|(KY)|(KZ)|(LA)|(LB)|(LC)|(LI)|(LK)|(LR)|(LS)|(LT)|(LU)|(LV)|(LY)|(MA)|(MC)|(MD)|(ME)|(MG)|(MH)|(MIL)|(MK)|(ML)|(MM)|(MN)|(MO)|(MOBI)|(MP)|(MQ)|(MR)|(MS)|(MT)|(MU)|(MUSEUM)|(MV)|(MW)|(MX)|(MY)|(MZ)|(NA)|(NAME)|(NC)|(NE)|(NET)|(NF)|(NG)|(NI)|(NL)|(NO)|(NP)|(NR)|(NU)|(NZ)|(OM)|(ORG)|(PA)|(PE)|(PF)|(PG)|(PH)|(PK)|(PL)|(PM)|(PN)|(POST)|(PR)|(PRO)|(PS)|(PT)|(PW)|(PY)|(QA)|(RE)|(RO)|(RS)|(RU)|(RW)|(SA)|(SB)|(SC)|(SD)|(SE)|(SG)|(SH)|(SI)|(SJ)|(SK)|(SL)|(SM)|(SN)|(SO)|(SR)|(ST)|(SU)|(SV)|(SX)|(SY)|(SZ)|(TC)|(TD)|(TEL)|(TF)|(TG)|(TH)|(TJ)|(TK)|(TL)|(TM)|(TN)|(TO)|(TP)|(TR)|(TRAVEL)|(TT)|(TV)|(TW)|(TZ)|(UA)|(UG)|(UK)|(US)|(UY)|(UZ)|(VA)|(VC)|(VE)|(VG)|(VI)|(VN)|(VU)|(WF)|(WS)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XN)|(XXX)|(YE)|(YT)|(ZA)|(ZM)|(ZW))([\/\w\.\-]*)*\/?/gi;
            msg = msg.replace(new RegExp(urlPattern), function (m) {
                var href = m;
                href = href.replace('http://', '');
                href = href.replace('https://', '');
                return '<a href="javascript:void(0);" data-href="' + href + '">' + m + '</a>';
            });

            return msg;
        },

        InitAudio: function () {
            if (! PMChat.UI.Config.Audio)
                return;

            try
            {
                var audio = new Audio()

                for (var event in PMChat.UI.Config.Audio) {
                    for (var i = 0; i < PMChat.UI.Config.Audio[event].length; i++) {
                        var path = PMChat.UI.Config.Audio[event][i];
                        if (path.substr(0, 1) == "~") {
                            path = PMChat.Config.BaseUrl + path.substr(1, path.length);
                        }
                        var format = PMChat.UI.ExtractAudioFormat(path);
                        if (audio.canPlayType(format)) {
                            PMChat.UI.Config.Audio[event] = new Audio(path);
                            break;
                        }
                    }
                }
            } catch (err)
            {
                PMChat.UI.Config.Audio = { };
                PMChat.Log("Unable to initialize audio");
            }
        },

        ExtractAudioFormat: function (urlPath) {
            var fmt = urlPath.split('.');
            if (fmt != null && fmt.length > 0) {
                return "audio/" + fmt[fmt.length - 1];
            }

            return "audio/unknown";
        },
        
        CalculateAge: function(birthDate) {
            var today = new Date();
            birthDate = new Date(birthDate);
            var age = today.getFullYear() - birthDate.getFullYear();
            var m = today.getMonth() - birthDate.getMonth();
            if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
                age--;
            }
            return age;
        },
        
        ParseDateForIE: function (s) {
            var bits = s.split(/[-T:]/g);
            var d = new Date(bits[0], bits[1] - 1, bits[2]);
            d.setHours(bits[3], bits[4], bits[5]);

            return d;
        },

        CalculateTimeStamp: function (sentDate) {
            var sent = moment(sentDate);    

            var threeMinAgo = moment().subtract('minutes', 3);
            var oneHourAgo = moment().subtract('hours', 1);
            var threeHoursAgo = moment().subtract('hours', 3);
            var today = moment().startOf('day');
            var yesterday = moment().subtract('days', 1);

            if (sent >= threeMinAgo)
                return "just now";

            if (sent >= oneHourAgo)
                return sent.startOf('minute').fromNow();

            if (sent >= threeHoursAgo) {
                return sent.startOf('hour').fromNow();
            }
            
            if (sent >= today)
                return "today";

            if (sent >= yesterday)
                return "yesterday";
            
            return sent.format('MM/DD/YYYY');
        }
    }
});

